package com.example.demo.service;

import com.example.demo.config.BizOrderStateMachineContextPersister;
import com.example.demo.dao.OrderRepository;
import com.example.demo.dao.StateMachineContextRepository;
import com.example.demo.domain.entity.OrderEntity;
import com.example.demo.domain.entity.StateMachineContextEntity;
import com.example.demo.domain.enums.OrderStatus;
import com.example.demo.domain.enums.OrderStatusChangeEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class OrderService {
    @Autowired
    private StateMachine<OrderStatus, OrderStatusChangeEvent> orderStateMachine;
    //  private final StateMachinePersister<OrderStatus, OrderStatusChangeEvent, String> stateMachineMemPersister;
    @Autowired()
    @Qualifier("bizOrderStateMachineContextPersister")
    private StateMachinePersister stateMachineMemPersister;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private StateMachineContextRepository stateMachineContextRepository;

    public OrderEntity create(OrderEntity order) {
        order.setStatus(OrderStatus.WAIT_PAYMENT);
        return orderRepository.save(order);
    }

    public OrderEntity pay(Long id) {
        OrderEntity order = findById(id);
        if (!sendEvent(OrderStatusChangeEvent.PAYED, order)) {
            log.error("线程名称：{},支付失败, 状态异常，订单信息：{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("支付失败, 订单状态异常");
        }
        return order;
    }


    public OrderEntity deliver(Long id) {
        OrderEntity order = findById(id);
        System.out.println("线程名称：" + Thread.currentThread().getName() + " 尝试发货，订单号：" + id);
        if (!sendEvent(OrderStatusChangeEvent.DELIVERY, order)) {
            System.out.println("线程名称：" + Thread.currentThread().getName() + " 发货失败，状态异常，订单号：" + id);
        }
        return order;
    }


    public OrderEntity receive(Long id) {
        OrderEntity order = findById(id);
        log.info("线程名称：{},尝试收货，订单号：{}", Thread.currentThread().getName(), id);
        if (!sendEvent(OrderStatusChangeEvent.RECEIVED, order)) {
            log.error("线程名称：{},收货失败, 状态异常，订单信息：{}", Thread.currentThread().getName(), order);
            throw new RuntimeException("收货失败, 订单状态异常");
        }
        return order;
    }

    private OrderEntity findById(Long id) {
        return orderRepository.findById(id).orElseThrow(() -> new RuntimeException("订单不存在"));
    }

    private synchronized boolean sendEvent(OrderStatusChangeEvent changeEvent, OrderEntity order) {
        boolean result = false;
        try {
            //启动状态机
            orderStateMachine.start();
            //尝试恢复状态机状态
            stateMachineMemPersister.restore(orderStateMachine, String.valueOf(order.getId()));
            Message message = MessageBuilder.withPayload(changeEvent)
                    .setHeader("order", order).build();
            result = orderStateMachine.sendEvent(message);
            //持久化状态机状态
            stateMachineMemPersister.persist(orderStateMachine, String.valueOf(order.getId()));
        } catch (Exception e) {
            log.error("订单操作失败:{}", e);
        } finally {
            orderStateMachine.stop();
        }
        return result;
    }

    public StateMachineContextEntity find() {
        return stateMachineContextRepository.findTopByOrderId("14");
    }
}
